package com.ys.erp.stage_mall_service.service;

import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ys.erp.common.enums.EnableEnum;
import com.ys.erp.common.enums.old.StatusOldEnum;
import com.ys.erp.common.enums.old.TypeOldEnum;
import com.ys.erp.common.util.MoneyUtil;
import com.ys.erp.common.util.YsThread;
import com.ys.erp.entity.data.bean.*;
import com.ys.erp.entity.service.*;
import com.ys.erp.framework.bean.dto.StageEmpDTO;
import com.ys.erp.framework.exception.YsException;
import com.ys.erp.framework.response.PageDTO;
import com.ys.erp.stage_mall_service.bean.condition.AfterSaleCondition;
import com.ys.erp.stage_mall_service.bean.vo.OrderAfterSaleVO;
import com.ys.erp.stage_mall_service.bean.vo.OrderGoodsVO;
import com.ys.erp.stage_mall_service.bean.vo.OrderVO;
import com.ys.erp.stage_mall_service.utils.WxUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @author lwj
 * @date 2025/5/22
 */
@Service
@RequiredArgsConstructor
@Slf4j
@RefreshScope
public class AfterSaleService {

    private final IOrderService iOrderService;

    private final IOrderGoodsService iOrderGoodsService;

    private final IToShopOrderService iToShopOrderService;

    private final IPayRecordService iPayRecordService;

    private final IUserService iUserService;

    private final IRefundRecordService iRefundRecordService;

    private final WxUtil wxUtil;

    private final IUserCatService iUserCatService;

    private final IUserCatMoneyRecordService iUserCatMoneyRecordService;

    private final IUserPulseService iUserPulseService;

    private final IUserPulseRecordService iUserPulseRecordService;

    private final IOrderAfterSaleService iOrderAfterSaleService;

    /**
     * 到店付订单退款
     *
     * @param empDTO            登录员工
     * @param con               请求体
     */
    public void refundToShopOrder(StageEmpDTO empDTO, AfterSaleCondition.RefundToShopOrderCon con) {
        LocalDateTime now = LocalDateTime.now();
        //查询订单
        CompletableFuture<Order> orderFuture = YsThread.execute(() -> {
            return iOrderService.getByNo(con.getOrderNo());
        });
        //查询到店付订单
        CompletableFuture<ToShopOrder> toShopOrderFuture = YsThread.execute(() -> {
            return iToShopOrderService.getByNo(con.getOrderNo());
        });
        Map<Long, AfterSaleCondition.RefundToShopOrderGoodsCon> conGoodsMap = con.getGoodsList().stream()
                .collect(Collectors.toMap(AfterSaleCondition.RefundToShopOrderGoodsCon::getOrderGoodsId, it -> it));
        //查询订单下商品
        CompletableFuture<List<OrderGoods>> orderGoodsListFuture = YsThread.execute(() -> {
            QueryWrapper<OrderGoods> orderGoodsQw = new QueryWrapper<>();
            orderGoodsQw.lambda().in(OrderGoods::getId, conGoodsMap.keySet());
            return iOrderGoodsService.list(orderGoodsQw);
        });
        Order order = orderFuture.join();
        CompletableFuture<User> userFuture = YsThread.execute(() -> {
            return iUserService.getById(order.getUserId());
        });
        ToShopOrder toShopOrder = toShopOrderFuture.join();
        Map<Long, OrderGoods> orderGoodsMap = orderGoodsListFuture.join().stream()
                .filter(it -> {
                    if (!it.getOrderId().equals(order.getId())) {
                        return false;
                    }
                    AfterSaleCondition.RefundToShopOrderGoodsCon refundGoodsCon = conGoodsMap.get(it.getId());
                    return !ObjectUtils.isEmpty(refundGoodsCon);
                })
                .collect(Collectors.toMap(OrderGoods::getId, it -> it));
        if (ObjectUtils.isEmpty(orderGoodsMap)) {
            throw new YsException(-1, "暂无可退的商品");
        }
        order.setIsAfterSale(EnableEnum.YES.getEnable());
        order.setAfterSaleTime(now);
        User user = userFuture.join();
        //处理商品
        orderGoodsMap.forEach((orderGoodsId, orderGoods) -> {
            AfterSaleCondition.RefundToShopOrderGoodsCon refundGoodsCon = conGoodsMap.get(orderGoodsId);
            if (refundGoodsCon.getNum() > orderGoods.getGoodsCount() - orderGoods.getAfterSaleNum()) {
                refundGoodsCon.setNum(orderGoods.getGoodsCount() - orderGoods.getAfterSaleNum());
            }
            orderGoods.setAfterSaleStatus(StatusOldEnum.AFTER_SALE_OK.getStatus());
            orderGoods.setAfterSaleNum(refundGoodsCon.getNum() + orderGoods.getAfterSaleNum());
            orderGoods.setAfterSaleTime(now);
            //计算退款单价
            BigDecimal ysMoney = new BigDecimal(orderGoods.getYsMoney());
            BigDecimal goodsCount = new BigDecimal(orderGoods.getGoodsCount());
            BigDecimal refundNum = new BigDecimal(refundGoodsCon.getNum());
            BigDecimal wxMoney = new BigDecimal(orderGoods.getWxMoney());
            BigDecimal pulseMoney = new BigDecimal(orderGoods.getYsPulseMoney());
            BigDecimal refundYsMoney = ysMoney.divide(goodsCount, 2, RoundingMode.HALF_UP).multiply(refundNum);
            BigDecimal refundWxMoney = wxMoney.divide(goodsCount, 2, RoundingMode.HALF_UP).multiply(refundNum);
            BigDecimal refundPulseMoney = pulseMoney.divide(goodsCount, 2, RoundingMode.HALF_UP).multiply(refundNum);
            ArrayList<RefundRecord> refundRecordList = new ArrayList<>();
            if (refundYsMoney.longValue() > 0) {
                //退幺币
                QueryWrapper<UserCat> userCatQw = new QueryWrapper<>();
                userCatQw.lambda().eq(UserCat::getUserId, order.getUserId())
                        .eq(UserCat::getCatCode, order.getPayCatCode())
                        .eq(UserCat::getIsDisable, EnableEnum.NO.getEnable());
                userCatQw.lambda().last("for update");
                List<UserCat> userCatsList = iUserCatService.list(userCatQw);
                if (userCatsList.size() != 1) {
                    throw new YsException(-1, "退款幺币错误");
                }
                UserCat userCat = userCatsList.getFirst();
                Long userCatMoney = userCat.getCatMoney() + order.getActualYsMoney();
                userCat.setCatMoney(userCatMoney);
                iUserCatService.updateById(userCat);
                //增加幺币记录
                UserCatMoneyRecord userCatMoneyRecord = new UserCatMoneyRecord();
                userCatMoneyRecord.setUserCatId(userCat.getId());
                userCatMoneyRecord.setCatCode(userCat.getCatCode());
                userCatMoneyRecord.setUserId(userCat.getUserId());
                userCatMoneyRecord.setRecordNum(ysMoney.longValue());
                userCatMoneyRecord.setCatMoneyBak(userCat.getCatMoney());
                userCatMoneyRecord.setRecordType(TypeOldEnum.CAT_MONEY_RECORD_INCOME.getType());
                userCatMoneyRecord.setIncomeType(TypeOldEnum.CAT_MONEY_GOODS_REJECT_MONEY_ADD.getType());
                userCatMoneyRecord.setRecordDescribe("订单退款");
                userCatMoneyRecord.setOrderId(order.getId());
                iUserCatMoneyRecordService.save(userCatMoneyRecord);
                RefundRecord refundRecord = new RefundRecord();
                refundRecord.setUserId(order.getUserId());
                refundRecord.setUserOpenId(user.getOpenId());
                refundRecord.setOrderId(order.getId());
                refundRecord.setPayRecordId(order.getOrderPayId());
                refundRecord.setRefundType(TypeOldEnum.REFUND_CATS.getType());
                refundRecord.setRefundStatus(StatusOldEnum.REFUND_SUCCESS.getStatus());
                refundRecord.setRefundTime(now);
                refundRecord.setRefundMoney(refundYsMoney.longValue());
                refundRecordList.add(refundRecord);
            }
            if (refundWxMoney.longValue() > 0) {
                //退微信
                List<Long> payIdList = order.getPayIdList();
                QueryWrapper<PayRecord> payRecordQw = new QueryWrapper<>();
                payRecordQw.lambda().eq(PayRecord::getPayType, TypeOldEnum.PAY_WX.getType());
                payRecordQw.lambda().in(PayRecord::getId, payIdList);
                PayRecord payRecord = iPayRecordService.getOne(payRecordQw);
                //退微信
                RefundRecord refundRecord = new RefundRecord();
                refundRecord.setUserId(order.getUserId());
                refundRecord.setUserOpenId(user.getOpenId());
                refundRecord.setOrderId(order.getId());
                refundRecord.setPayRecordId(order.getOrderPayId());
                refundRecord.setRefundType(TypeOldEnum.REFUND_WX.getType());
                refundRecord.setWxOutTradeNo(payRecord.getWxOutTradeNo());
                refundRecord.setRefundStatus(StatusOldEnum.REFUND_START.getStatus());
                refundRecord.setRefundTime(now);
                refundRecord.setWxRefundNo("refund_" + payRecord.getWxOutTradeNo() + "_" + (100000 + new Random().nextInt(900000)));
                refundRecord.setRefundMoney(refundWxMoney.longValue());
                refundRecordList.add(refundRecord);
                wxUtil.refund(refundRecord, order.getActualWxMoney());
            }
            //退幺豆
            if (refundPulseMoney.longValue() > 0) {
                UserPulse userPulse = iUserPulseService.getByUserId(order.getUserId());
                userPulse.setPulseNum(userPulse.getPulseNum() + refundPulseMoney.longValue());
                iUserPulseService.updateById(userPulse);
                UserPulseRecord pulseRecord = new UserPulseRecord();
                pulseRecord.setUserId(order.getUserId());
                pulseRecord.setPulseNo(userPulse.getPulseNo());
                pulseRecord.setRecordType(UserPulseRecord.Enums.IN.name());
                pulseRecord.setInOutType(UserPulseRecord.Enums.ORDER_REFUND.name());
                pulseRecord.setRecordNum(refundPulseMoney.longValue());
                pulseRecord.setRecordTime(now);
                pulseRecord.setRelaNo(order.getOrderSerialNumber());
                pulseRecord.setEmpId(empDTO.getId());
                pulseRecord.setEmpName(empDTO.getRealName());
                iUserPulseRecordService.save(pulseRecord);
            }
            iRefundRecordService.saveBatch(refundRecordList);
            String refundRecordIdList = String.join(",", refundRecordList.stream().map(it -> it.getId().toString()).toList());
            //创建一个售后订单，并且自动打款
            OrderAfterSale orderAfterSale = new OrderAfterSale();
            orderAfterSale.setApplyEmpId(empDTO.getId());
            orderAfterSale.setOrderId(order.getId());
            orderAfterSale.setOrderSerialNo(order.getOrderSerialNumber());
            orderAfterSale.setUserId(order.getUserId());
            orderAfterSale.setAfterSaleType(TypeOldEnum.PROCURE_ONLY_REFUND.getType());
            orderAfterSale.setOrderGoodsId(orderGoodsId);
            orderAfterSale.setAfterSaleStatus(StatusOldEnum.AFTER_SALE_OK.getStatus());
            orderAfterSale.setIsAgreeAfterSale(EnableEnum.YES.getEnable());
            orderAfterSale.setAfterSaleTime(now);
            orderAfterSale.setOkTime(now);
            orderAfterSale.setPassTime(now);
            orderAfterSale.setRejectMoney(ysMoney.longValue() + wxMoney.longValue());
            orderAfterSale.setRejectWxMoney(wxMoney.longValue());
            orderAfterSale.setRejectYsMoney(ysMoney.longValue());
            orderAfterSale.setRefundRecordId(refundRecordIdList);
            iOrderAfterSaleService.save(orderAfterSale);
        });

    }

    /**
     * 分页售后订单
     *
     * @param empDTO                登录员工
     * @param con                   请求体
     * @return                      分页数据
     */
    public PageDTO<OrderAfterSaleVO> pageOrderAfterSale(StageEmpDTO empDTO, AfterSaleCondition.PageOrderAfterSaleCon con) {
        Page<OrderAfterSale> orderAfterSalePage = new Page<>(con.getCurrent(), con.getSize());
        QueryWrapper<OrderAfterSale> orderAfterSaleQw = new QueryWrapper<>();
        orderAfterSaleQw.lambda().orderByDesc(OrderAfterSale::getId);
        if (ObjectUtils.isNotEmpty(con.getStatus())) {
            orderAfterSaleQw.lambda().eq(OrderAfterSale::getAfterSaleStatus, con.getStatus());
        }
        //查询
        Page<OrderAfterSale> page = iOrderAfterSaleService.page(orderAfterSalePage, orderAfterSaleQw);
        if (page.getRecords().isEmpty()) {
            return new PageDTO<>(page.getCurrent(), page.getTotal(), new ArrayList<>());
        }
        List<Long> orderGoodsIds = new ArrayList<>();
        List<Long> orderIds = new ArrayList<>();
        List<Long> userIds = new ArrayList<>();
        for (OrderAfterSale sale : page.getRecords()) {
            orderGoodsIds.add(sale.getOrderGoodsId());
            orderIds.add(sale.getOrderId());
            userIds.add(sale.getUserId());
        }
        CompletableFuture<Map<Long, User>> userMapFuture = YsThread.execute(() -> {
            return iUserService.listByIds(userIds).stream()
                    .collect(Collectors.toMap(User::getId, it -> it));
        });
        CompletableFuture<Map<Long, Order>> orderMapFuture = YsThread.execute(() -> {
            return iOrderService.listByIds(orderIds).stream()
                    .collect(Collectors.toMap(Order::getId, it -> it));
        });
        CompletableFuture<Map<Long, OrderGoods>> orderGoodsMapFuture = YsThread.execute(() -> {
            return iOrderGoodsService.listByIds(orderGoodsIds).stream()
                    .collect(Collectors.toMap(OrderGoods::getId, it -> it));
        });
        Map<Long, User> userMap = userMapFuture.join();
        Map<Long, Order> orderMap = orderMapFuture.join();
        Map<Long, OrderGoods> orderGoodsMap = orderGoodsMapFuture.join();
        //整理数据
        List<OrderAfterSaleVO> collect = page.getRecords().stream()
                .map(it -> {
                    OrderAfterSaleVO vo = new OrderAfterSaleVO();
                    BeanUtils.copyProperties(it, vo);
                    vo.setRejectMoney(MoneyUtil.long2Str(it.getRejectMoney()));
                    Order order = orderMap.get(it.getOrderId());
                    if (Objects.isNull(order)) {
                        return vo;
                    }
                    OrderVO orderVO = new OrderVO();
                    BeanUtils.copyProperties(order, orderVO);
                    orderVO.setPayType(order.getPayType());
                    OrderGoods orderGoods = orderGoodsMap.get(it.getOrderGoodsId());
                    OrderGoodsVO orderGoodsVo = new OrderGoodsVO();
                    BeanUtils.copyProperties(orderGoods, orderGoodsVo);
                    orderGoodsVo.setSubtotal(MoneyUtil.long2Str(orderGoods.getSubtotal()));
                    orderGoodsVo.setDeliveryMoney(MoneyUtil.long2Str(orderGoods.getDeliveryMoney()));
                    orderGoodsVo.setGoodsSpecs(orderGoods.getSpecsDes());
                    vo.setOrder(orderVO);
                    vo.setPayType(order.getPayType());
                    vo.setRejectWxMoney(MoneyUtil.long2Str(it.getRejectWxMoney()));
                    vo.setRejectYsMoney(MoneyUtil.long2Str(it.getRejectYsMoney()));
                    vo.setUserVoucher(JSONArray.parseArray(it.getUserVoucher(), String.class));
                    vo.setOrderGoods(orderGoodsVo);
                    vo.setRejectMoney(MoneyUtil.long2Str(it.getRejectMoney()));

                    // 设置该订单可退还的幺豆数量
                    Long refundPulseNum = order.getYsPulseNum();
                    vo.setYsPulse(MoneyUtil.long2Str(refundPulseNum));

                    return vo;
                }).collect(Collectors.toList());
        return new PageDTO<>(page.getCurrent(), page.getTotal(), collect);
    }

    /**
     * 通过售后单退还幺豆
     *
     * @param empDTO            登录员工
     * @param con               请求体
     */
    public void refundPulseByAfterSale(StageEmpDTO empDTO, AfterSaleCondition.RefundPulseByAfterSaleCon con) {
        LocalDateTime now = LocalDateTime.now();
        
        // 查询售后单
        OrderAfterSale afterSale = iOrderAfterSaleService.getById(con.getAfterSaleId());
        if (ObjectUtils.isEmpty(afterSale)) {
            throw new YsException(-1, "售后单不存在");
        }
        
        // 验证售后单状态
        if (!afterSale.getAfterSaleStatus().equals(StatusOldEnum.AFTER_SALE_BUS_DISPOSE.getStatus())) {
            throw new YsException(-1, "售后单状态不允许退还幺豆");
        }
        
        // 验证售后单是否已同意
//        if (!afterSale.getIsAgreeAfterSale().equals(EnableEnum.YES.getEnable())) {
//            throw new YsException(-1, "售后单未通过审核，不能退还幺豆");
//        }
        
        // 查询原订单信息
        Order order = iOrderService.getById(afterSale.getOrderId());
        if (ObjectUtils.isEmpty(order)) {
            throw new YsException(-1, "原订单不存在");
        }

                // 直接获取订单使用的幺豆数量
        Long refundPulseNum = order.getYsPulseNum();
        
        if (refundPulseNum == null || refundPulseNum <= 0) {
            throw new YsException(-1, "该订单没有可退还的幺豆");
        }

        // 查询用户幺豆信息
        UserPulse userPulse = iUserPulseService.getByUserId(afterSale.getUserId());
        if (ObjectUtils.isEmpty(userPulse)) {
            throw new YsException(-1, "用户幺豆信息不存在");
        }
        
        // 更新用户幺豆余额
        userPulse.setPulseNum(userPulse.getPulseNum() + refundPulseNum);
        iUserPulseService.updateById(userPulse);
        if (order.getTotalMoney() == 0L) {
            afterSale.setAfterSaleStatus(StatusOldEnum.AFTER_SALE_OK.getStatus());
            afterSale.setOkTime(now);
            afterSale.setPassTime(now);
            iOrderAfterSaleService.updateById(afterSale);
        }
        // 创建幺豆记录
        UserPulseRecord pulseRecord = new UserPulseRecord();
        pulseRecord.setUserId(afterSale.getUserId());
        pulseRecord.setPulseNo(userPulse.getPulseNo());
        pulseRecord.setRecordType(UserPulseRecord.Enums.IN.name());
        pulseRecord.setInOutType(UserPulseRecord.Enums.ORDER_REFUND.name());
        pulseRecord.setRecordNum(refundPulseNum);
        pulseRecord.setRecordTime(now);
        pulseRecord.setRelaNo(afterSale.getOrderSerialNo());
        pulseRecord.setEmpId(empDTO.getId());
        pulseRecord.setEmpName(empDTO.getRealName());
        pulseRecord.setRemark(ObjectUtils.isEmpty(con.getRemark()) ? "售后单退还幺豆" : con.getRemark());
        iUserPulseRecordService.save(pulseRecord);
        
        log.info("售后单[{}]成功退还幺豆[{}]给用户[{}]，操作员[{}]", 
                afterSale.getId(), refundPulseNum, afterSale.getUserId(), empDTO.getRealName());
    }

}
